{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true,
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "# Python基础教程 面向对象"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "outputs": [],
   "source": [
    "#Python是一门更纯粹面向对象的语言\n",
    "#Python中面向对象的语法十分简介"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [],
   "source": [
    "#创建类\n",
    "class Person:\n",
    "    '''人 类'''\n",
    "\n",
    "    #定义构造函数\n",
    "    def __init__(self,name,age):\n",
    "        self.name=name\n",
    "        self.age=age\n",
    "    def display(self):\n",
    "        print(\"person(姓名:{},年龄:{})\".format(self.name,self.age))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "以双下划线开头的函数我们叫它魔法函数，__init__函数表示类的初始构造函数，这是Python的语法限制，初始构造函数可以有其他参数也可以没有，但是必须写个self"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "类中添加成员变量，要在初始构造函数里面写self.变量名字 = xxxxx，无需指定变量类型（你也能通过一些方法指定）"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "类中添加方法，函数的第一参数必须是self"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "self相当于C++中的this指针"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "LYX\n",
      "19\n"
     ]
    }
   ],
   "source": [
    "#创建对象\n",
    "p2=Person(\"LYX\",19)\n",
    "print(p2.name)\n",
    "print(p2.age)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "person(姓名:LYX,年龄:19)\n"
     ]
    }
   ],
   "source": [
    "p2.display()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [],
   "source": [
    "#类属性 即静态成员变量\n",
    "#创建一个表示人的类\n",
    "class  Person:\n",
    "    '''表示人的基本信息'''\n",
    "    pernum=0   #类属性\n",
    "    #定义类的构造函数，初始化类的基本信息\n",
    "    def __init__(self,name,age):\n",
    "        self.name= name\n",
    "        self.age=age\n",
    "        Person.pernum+=1\n",
    "    def display(self):\n",
    "        print(\"person(姓名:{},年龄:{})\".format(self.name,self.age))\n",
    "    def display_pernum(self):\n",
    "        print(Person.pernum)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "1\n",
      "2\n",
      "2\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "p3=Person(\"杜甫\",32)\n",
    "print(p3.pernum)\n",
    "p3.display_pernum()\n",
    "p4=Person(\"王安石\",42)\n",
    "print(Person.pernum)\n",
    "print(p4.pernum)\n",
    "p4.display_pernum()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 限制访问"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "开头为两个下划线(__)的成员变量或者类属性，都是私有"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "outputs": [],
   "source": [
    "#创建一个表示人的类\n",
    "class  Person:\n",
    "    '''表示人的基本信息'''\n",
    "    pernum=0   #类属性\n",
    "    __percount=1000  #定义类的私有属性\n",
    "\n",
    "    #定义类的构造函数，初始化类的基本信息\n",
    "    def __init__(self,name,age):\n",
    "        self.name= name\n",
    "        self.age=age\n",
    "        Person.pernum+=1\n",
    "        self.__pwd=123456   ##实例私有属性\n",
    "    def display(self):\n",
    "        print(\"person(姓名:{},年龄:{})\".format(self.name,self.age))\n",
    "    def display_pernum(self):\n",
    "        print(Person.pernum)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "outputs": [
    {
     "ename": "AttributeError",
     "evalue": "'Person' object has no attribute 'percount'",
     "output_type": "error",
     "traceback": [
      "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[1;31mAttributeError\u001B[0m                            Traceback (most recent call last)",
      "\u001B[1;32mC:\\Users\\ADMINI~1\\AppData\\Local\\Temp/ipykernel_620/3348548335.py\u001B[0m in \u001B[0;36m<module>\u001B[1;34m\u001B[0m\n\u001B[0;32m      1\u001B[0m \u001B[0mp2\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mPerson\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;34m\"LYX\"\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;36m19\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m----> 2\u001B[1;33m \u001B[0mprint\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mp2\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mpercount\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m",
      "\u001B[1;31mAttributeError\u001B[0m: 'Person' object has no attribute 'percount'"
     ]
    }
   ],
   "source": [
    "p2=Person(\"LYX\",19)\n",
    "print(p2.percount)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 装饰器"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "outputs": [],
   "source": [
    "class  Person:\n",
    "    '''表示人的基本信息'''\n",
    "    pernum=0   #类属性\n",
    "    __percount=1000  #定义类的私有属性\n",
    "\n",
    "    #定义类的构造函数，初始化类的基本信息\n",
    "    def __init__(self,name,age):\n",
    "        self.name= name\n",
    "        self.age=age\n",
    "        Person.pernum+=1\n",
    "        self.__pwd=123456   ##实例私有属性\n",
    "    def display(self):\n",
    "        print(\"person(姓名:{},年龄:{})\".format(self.name,self.age))\n",
    "    #通过添加装饰器，把方法变为属性\n",
    "    @property\n",
    "    def display_pernum(self):\n",
    "        print(Person.pernum)\n",
    "    #通过添加装饰器，把私有属性变为只读属性\n",
    "    @property\n",
    "    def display_percount(self):\n",
    "        return Person.__percount"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n"
     ]
    },
    {
     "data": {
      "text/plain": "1000"
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#现在我们可以像访问成员变量一样调用函数了\n",
    "p6=Person(\"苏轼\",43)\n",
    "#调用方法，转换为调用属性一样\n",
    "p6.display_pernum  #1\n",
    "#访问私有属性，但不能修改\n",
    "p6.display_percount  #1000"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n"
     ]
    }
   ],
   "source": [
    "p6.display_pernum"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 继承"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "outputs": [],
   "source": [
    "#新建Student类 它继承Person类\n",
    "#子类继承父类属性和方法 但是重写父类方法，父类方法不会执行\n",
    "#若要执行父类方法，可以采用super().父类方法"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "outputs": [],
   "source": [
    "#对于父类的魔法方法__init__同样如此，为了调用父类的初始化方法__init__,使用super(subclass,sefl).__init__()或super().__init__()即可。"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "outputs": [],
   "source": [
    "class Person:\n",
    "    '''人 类'''\n",
    "\n",
    "    #定义构造函数\n",
    "    def __init__(self,name,age):\n",
    "        self.name=name\n",
    "        self.age=age\n",
    "    def display(self):\n",
    "        print(\"人类，姓名:{}，年龄:{}\".format(self.name,self.age))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "outputs": [],
   "source": [
    "class Student(Person):\n",
    "    '''学生类 继承自Person'''\n",
    "    #定义子类构造函数\n",
    "    def __init__(self,name,age,major):\n",
    "        super(Student,self).__init__(name,age)  #调用父类构造函数部分构造\n",
    "        self.major=major\n",
    "\n",
    "    def display(self):\n",
    "        #重写父类中的display\n",
    "        print(\"学生，姓名:{}，年龄：{}，专业：{}\".format(self.name,self.age,self.major))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "人工智能\n",
      "学生，姓名:李三三，年龄：19，专业：人工智能\n"
     ]
    }
   ],
   "source": [
    "#实例化子类\n",
    "stu1=Student(\"李三三\",19,\"人工智能\")\n",
    "print(stu1.major)\n",
    "stu1.display()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "学生类 继承自Person\n"
     ]
    }
   ],
   "source": [
    "print(Student.__doc__)  #查看Student类的文档"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "outputs": [],
   "source": [
    "#重写父类方法 Python中直接在子类重写父类方法即可"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "super()表示父类\n",
    "更严格来说表示执行MRO（Method Resoluthion Order）顺序中的下一个类)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "super很棒"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "outputs": [],
   "source": [
    "#父类不会自动调用__init__方法\n",
    "class A:\n",
    "    def __init__(self,a):\n",
    "        A='A'\n",
    "        self.a=a\n",
    "        print('init A')\n",
    "\n",
    "class B(A):\n",
    "    def __init__(self,b):\n",
    "        self.b=b\n",
    "        print('init B')"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "init B\n"
     ]
    }
   ],
   "source": [
    "b=B('Python')  #并没有调用A.__init__"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "outputs": [],
   "source": [
    "#使用super表示父类\n",
    "class B(A):\n",
    "    def __init__(self,a,b):\n",
    "        super().__init__(a)\n",
    "        self.b=b\n",
    "        print('init B')"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "init A\n",
      "init B\n"
     ]
    }
   ],
   "source": [
    "b=B(1,2)   #其中也调用了A类的__init__方法"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "C.__init__\n",
      "A.__init__\n",
      "B.__init__\n",
      "A.__init__\n"
     ]
    }
   ],
   "source": [
    "#使用类名.init()可能导致重复执行\n",
    "class A(object):\n",
    "    def __init__(self):\n",
    "        print(\"A.__init__\")\n",
    "\n",
    "class B(A):\n",
    "    def __init__(self):\n",
    "        print(\"B.__init__\")\n",
    "        A.__init__(self)\n",
    "\n",
    "class C(B,A):\n",
    "    def __init__(self):\n",
    "        print(\"C.__init__\")\n",
    "        A.__init__(self)\n",
    "        B.__init__(self)\n",
    "\n",
    "c = C()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "C.__init__\n",
      "B.__init__\n",
      "A.__init__\n"
     ]
    }
   ],
   "source": [
    "#使用super来避免重复执行\n",
    "class A:\n",
    "    def __init__(self):\n",
    "        print(\"A.__init__\")\n",
    "\n",
    "class B(A):\n",
    "    def __init__(self):\n",
    "        print(\"B.__init__\")\n",
    "        super(B, self).__init__()\n",
    "\n",
    "class C(B,A):\n",
    "    def __init__(self):\n",
    "        print(\"C.__init__\")\n",
    "        super(C, self).__init__()\n",
    "\n",
    "c = C()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "# Python面向对象远远不止这些 后续再看"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}